﻿using DBUtil.Attributes;
using DotNetCommon.Extensions;
using NUnit.Framework;
using Shouldly;
using System;
using System.ComponentModel.DataAnnotations.Schema;

namespace Test.MySql.JsonTests.Primitives
{
    [TestFixture]
    internal class SimpleTypeTests_enum : TestBase
    {
        #region'model
        [Table("test")]
        public class Person
        {
            [PrimaryKey(KeyStrategy = KeyStrategy.Identity)]
            [Column("id")]
            public int Id { get; set; }

            [JsonStore(Bucket = "p_enum")]
            public EnumTest p_enum { get; set; }
            [JsonStore(Bucket = "p_enum_null")]
            public EnumTest? p_enum_null { get; set; }
            [JsonStore(Bucket = "p_enum_flag")]
            public EnumTestFlag p_enum_flag { get; set; }
            [JsonStore(Bucket = "p_enum_flag_null")]
            public EnumTestFlag? p_enum_flag_null { get; set; }
        }
        [Table("test2")]
        public class PersonKey
        {
            [PrimaryKey(KeyStrategy = KeyStrategy.Identity)]
            [Column("id")]
            public int Id { get; set; }

            [JsonStore(Bucket = "ext", Key = "p_enum")]
            public EnumTest p_enum { get; set; }
            [JsonStore(Bucket = "ext", Key = "p_enum_null")]
            public EnumTest? p_enum_null { get; set; }
            [JsonStore(Bucket = "ext", Key = "p_enum_flag")]
            public EnumTestFlag p_enum_flag { get; set; }
            [JsonStore(Bucket = "ext", Key = "p_enum_flag_null")]
            public EnumTestFlag? p_enum_flag_null { get; set; }
        }
        public enum EnumTest
        {
            A, B, C
        }
        [Flags]
        public enum EnumTestFlag
        {
            A = 1, B = 2, C = 4
        }
        #endregion

        [SetUp]
        public void SetUp()
        {
            DropTableIfExist("test");
            db.ExecuteSql("""
                create table test(id int auto_increment primary key,p_enum json,p_enum_null json,p_enum_flag json,p_enum_flag_null json)
                """);
            db.ExecuteSql("""
                insert into test(p_enum,p_enum_null,p_enum_flag,p_enum_flag_null) values
                    (cast(0 as json),cast(1 as json),cast(5 as json),cast(2 as json)),
                    (cast(1 as json),null,cast(5 as json),null);
                """);

            DropTableIfExist("test2");
            db.ExecuteSql("""
                create table test2(id int auto_increment primary key,ext json)
                """);
            db.ExecuteSql("""
                insert into test2(ext) values
                    (json_object("p_enum",0,"p_enum_null",1,"p_enum_flag",5,"p_enum_flag_null",2)),
                    (json_object("p_enum",1,"p_enum_null",null,"p_enum_flag",5,"p_enum_flag_null",null));
                """);
        }

        #region NoKey
        [Test]
        public void TestSelect()
        {
            var list = db.Select<Person>().Where(i => i.p_enum == EnumTest.A).ToList();
            var json = list.ToJson();
            json.ShouldBe("""[{"Id":1,"p_enum":0,"p_enum_null":1,"p_enum_flag":5,"p_enum_flag_null":2}]""");
        }

        [Test]
        public void TestInsert()
        {
            var sql = db.Insert<Person>().SetEntity(
              [
                new Person { p_enum=EnumTest.A,p_enum_null=EnumTest.B,p_enum_flag=EnumTestFlag.A|EnumTestFlag.C,p_enum_flag_null=EnumTestFlag.B},
                new Person { p_enum=EnumTest.B,p_enum_null=null,p_enum_flag=EnumTestFlag.A|EnumTestFlag.C,p_enum_flag_null=null},
            ]).ToSql();
        }

        [Test]
        public void TestUpdate()
        {
            var update = db.Update<Person>().SetEntity(new Person
            {
                Id = 1,
                p_enum = EnumTest.B,
                p_enum_flag = EnumTestFlag.B | EnumTestFlag.C,
                p_enum_flag_null = null,
            });
            var r = update.ExecuteAffrows();
            r.ShouldBe(1);
            var p = db.Select<Person>().Where(i => i.Id == 1).FirstOrDefault();
            var json = p.ToJson();
            json.ShouldBe("""{"Id":1,"p_enum":1,"p_enum_null":null,"p_enum_flag":6,"p_enum_flag_null":null}""");
        }
        #endregion

        #region Key
        [Test]
        public void TestSelectKey()
        {
            var list = db.Select<PersonKey>().Where(i => i.p_enum == EnumTest.A).ToList();
            var json = list.ToJson();
            json.ShouldBe("""[{"Id":1,"p_enum":0,"p_enum_null":1,"p_enum_flag":5,"p_enum_flag_null":2}]""");
        }

        [Test]
        public void TestInsertKey()
        {
            var sql = db.Insert<PersonKey>().SetEntity(
              [
                new PersonKey { p_enum=EnumTest.A,p_enum_null=EnumTest.B,p_enum_flag=EnumTestFlag.A|EnumTestFlag.C,p_enum_flag_null=EnumTestFlag.B},
                new PersonKey { p_enum=EnumTest.B,p_enum_null=null,p_enum_flag=EnumTestFlag.A|EnumTestFlag.C,p_enum_flag_null=null},
            ]).ToSql();
        }

        [Test]
        public void TestUpdateKey()
        {
            var update = db.Update<PersonKey>().SetEntity(new PersonKey
            {
                Id = 1,
                p_enum = EnumTest.B,
                p_enum_flag = EnumTestFlag.B | EnumTestFlag.C,
                p_enum_flag_null = null,
            });
            var r = update.ExecuteAffrows();
            r.ShouldBe(1);
            var p = db.Select<PersonKey>().Where(i => i.Id == 1).FirstOrDefault();
            var json = p.ToJson();
            json.ShouldBe("""{"Id":1,"p_enum":1,"p_enum_null":null,"p_enum_flag":6,"p_enum_flag_null":null}""");
        }
        #endregion
    }
}
